package com.wang.mall.oauth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wang.mall.oauth.bean.SysMenu;
import com.wang.mall.oauth.bean.SysRole;
import com.wang.mall.oauth.bean.SysUser;
import com.wang.mall.oauth.bean.UmsMember;
import com.wang.mall.oauth.constant.LoginConstant;
import com.wang.mall.oauth.service.SysMenuService;
import com.wang.mall.oauth.service.SysRoleService;
import com.wang.mall.oauth.service.SysUserService;
import com.wang.mall.oauth.service.UmsMemberService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceDetailsServiceImpl implements UserDetailsService {


    @Autowired
    private SysUserService sysUserService;


    @Autowired
    private SysRoleService sysRoleService;


    @Autowired
    private SysMenuService sysMenuService;


    @Autowired
    private UmsMemberService umsMemberService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        // 区分是后台人员还是我们的用户
        assert requestAttributes != null;
        String loginType = requestAttributes.getRequest().getParameter("login_type");
        if (StringUtils.isEmpty(loginType)) {
            throw new AuthenticationServiceException("登录类型不能为null");
        }

        String grantType = requestAttributes.getRequest().getParameter("grant_type");
        UserDetails userDetails = null;
        // 判断请求是否是刷新token
        if (LoginConstant.REFRESH_TYPE.equals(grantType.toUpperCase())) {
            // 因为refresh_token时，需要将id->username
            username = adjustUsername(username, loginType);
        }


        // 判断登录用户类型
        switch (loginType) {
            case LoginConstant.ADMIN_TYPE: // 系统用户登录
                userDetails = loadSysUserByUsername(username);
                break;
            case LoginConstant.MEMBER_TYPE: // 管理员登陆
                userDetails = loadMemberUserByUsername(username);
                break;
            default:
                throw new AuthenticationServiceException("暂不支持的登陆方式" + loginType);
        }

        return userDetails;
    }

    /**
     * 前台会员登陆
     *
     * @param username
     * @return
     */
    private UserDetails loadMemberUserByUsername(String username) {
        UmsMember member = umsMemberService.getOne(new LambdaQueryWrapper<UmsMember>().eq(UmsMember::getUsername, username));
        if (member == null) {
            throw new UsernameNotFoundException("会员" + username + "不存在");
        }

        Long id = member.getId();
        String password = member.getPassword();
        Byte status = member.getStatus();


        // 构建会员的权限
        ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();
        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
        authorities.add(simpleGrantedAuthority);

        return new User(String.valueOf(id),
                password,
                status == 1,
                true,
                true,
                true,
                authorities);

    }

    /**
     * 管理人员登录
     *
     * @param username
     * @return
     */
    private UserDetails loadSysUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        if (sysUser == null) {
            throw new UsernameNotFoundException("用户名不存在" + username);
        }

        String userId = String.valueOf(sysUser.getUserId());
        String password = sysUser.getPassword();
        Byte status = sysUser.getStatus();

        return new User(userId,
                password,
                status == 1,
                true,
                true,
                true,
                getSysUserPermissions(sysUser.getUserId()));
    }

    /**
     * 获取管理人员的权限信息
     *
     * @param userId
     * @return
     */
    private Collection<? extends GrantedAuthority> getSysUserPermissions(Long userId) {
        List<String> permissions = null;

        // 查询角色
        List<SysRole> userRoleList = sysRoleService.findByUserId(userId);
        List<String> roleName = userRoleList.stream().map(SysRole::getRoleName).collect(Collectors.toList());
        if (roleName.contains(LoginConstant.ADMIN)) {
            // 超级管理员权限, 查询所有权限
            List<SysMenu> menuList = sysMenuService.list();
            permissions = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());

        } else {
            // 非超级管理员
            List<Long> roldIds = userRoleList.stream().map(SysRole::getRoleId).collect(Collectors.toList());
            // 用户分配角色
            if (CollectionUtils.isEmpty(roldIds)) { // 如果没有权限就返回一个空的集合
                return new ArrayList<SimpleGrantedAuthority>();
            }

            //根据角色ID查询权限
            List<SysMenu> sysMenuList = sysMenuService.findMenuByRoleIds(roldIds);

            permissions = sysMenuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
        }

        List<SimpleGrantedAuthority> collect = permissions.stream().distinct().map(SimpleGrantedAuthority::new).collect(Collectors.toList());

        return collect;
    }


    /**
     * 根据更具用户名查询ID
     *
     * @param username
     * @param loginType
     * @return
     */
    private String adjustUsername(String username, String loginType) {
        // 如果是管理员登陆
        if (LoginConstant.ADMIN_TYPE.equals(loginType)) {
            return sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username)).getUserId().toString();
        }

        // 如果时会员登录
        if (LoginConstant.MEMBER_TYPE.equals(loginType)) {
            return umsMemberService.getOne(new LambdaQueryWrapper<UmsMember>().eq(UmsMember::getUsername, username)).getId().toString();
        }

        return username;
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println("encode = " + encode);
    }
}
